/**
 * Copyright &copy; 2021-2026 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
 */
package com.jeeplus.database.datamodel.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeeplus.common.utils.ResponseUtil;
import com.jeeplus.core.query.QueryWrapperGenerator;
import com.jeeplus.database.datalink.jdbc.DBPool;
import com.jeeplus.database.datamodel.domain.DataMeta;
import com.jeeplus.database.datamodel.domain.DataParam;
import com.jeeplus.database.datamodel.domain.DataSet;
import com.jeeplus.database.datamodel.service.DataMetaService;
import com.jeeplus.database.datamodel.service.DataParamService;
import com.jeeplus.database.datamodel.service.DataSetService;
import com.jeeplus.database.datamodel.service.dto.DataSetDTO;
import net.sf.json.JSONArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;

/**
 * 数据模型Controller
 *
 * @author 刘高峰
 * @version 2021-08-07
 */
@RestController
@RequestMapping(value = "/database/datamodel/dataSet")
public class DataSetController {

    @Autowired
    private DataSetService dataSetService;
    @Autowired
    private DataMetaService dataMetaService;
    @Autowired
    private DataParamService dataParamService;
    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 数据模型列表数据
     */
    @PreAuthorize("hasAuthority('database:datamodel:dataSet:list')")
    @GetMapping(value = "list")
    public ResponseEntity data(DataSetDTO dataSetDTO, Page <DataSetDTO> page) throws Exception {
        QueryWrapper <DataSetDTO> queryWrapper = QueryWrapperGenerator.buildQueryCondition ( dataSetDTO, DataSetDTO.class );
        IPage <DataSetDTO> result = dataSetService.findPage ( page, queryWrapper );
        return ResponseEntity.ok ( result );
    }


    /**
     * 查看，增加，编辑数据模型表单页面
     * params:
     * mode: add, edit, view, 代表三种模式的页面
     */
    @PreAuthorize("hasAnyAuthority('database:datamodel:dataSet:view','database:datamodel:dataSet:add','database:datamodel:dataSet:edit')")
    @GetMapping(value = "queryById")
    public ResponseEntity queryById(String id) {
        DataSetDTO dataSetDTO = dataSetService.detail ( id );
        return ResponseEntity.ok ( dataSetDTO );
    }


    /**
     * 保存数据模型
     */
    @PreAuthorize("hasAnyAuthority('database:datamodel:dataSet:add','database:datamodel:dataSet:edit')")
    @PostMapping(value = "save")
    public ResponseEntity save(@RequestBody @Valid DataSetDTO dataSetDTO) {

        //新增或编辑表单保存
        dataSetService.saveOrUpdate ( dataSetDTO );//保存
        return ResponseEntity.ok ( "保存数据模型成功" );
    }


    /**
     * 批量删除数据模型
     */
    @PreAuthorize("hasAuthority('database:datamodel:dataSet:del')")
    @DeleteMapping(value = "delete")
    public ResponseEntity delete(@RequestParam(value = "ids") String ids) {
        String idArray[] = ids.split ( "," );
        StringBuffer msg = new StringBuffer ( );
        for (String id : idArray) {
            List <Map <String, Object>> list = jdbcTemplate.queryForList ( "select name from plugin_echarts where data_set_id = '" + id + "'" );
            if ( list.size ( ) > 0 ) {
                String name = "";
                for (Map <String, Object> map : list) {
                    name = name + " [" + map.get ( "name" ).toString ( ) + "]";
                }
                msg.append ( "数据模型 [" + dataSetService.getById ( id ).getName ( ) + "] 已被图表" + name + " 使用，无法删除。请先删除图表，再删除该数据模型。" );
            } else {
                dataMetaService.lambdaUpdate ( ).eq ( DataMeta::getDataSetId, id ).remove ( );
                dataParamService.lambdaUpdate ( ).eq ( DataParam::getDataSetId, id ).remove ( );
                msg.append ( "删除数据模型 [" + dataSetService.getById ( id ).getName ( ) + "] 成功。" );
                dataSetService.delete ( id );
            }
        }
        return ResponseEntity.ok ( msg.toString ( ) );
    }


    /**
     * 执行sql 获取表结构
     */

    @GetMapping(value = "getMeta")
    public ResponseEntity query(@RequestParam(value = "dataSourceId", required = false) String dataSourceId, @RequestParam(value = "sql", required = false) String sql, @RequestParam(value = "field[]", required = false) String[] field, @RequestParam(value = "defaultValue[]", required = false) String[] defaultValue) throws IOException, SQLException {
        List columnList = new ArrayList ( );
        JdbcTemplate jdbcTemplate = DBPool.getInstance ( ).getJdbcTemplateByDsId ( dataSourceId );
        if ( jdbcTemplate == null ) {
            return ResponseEntity.badRequest ( ).body ( "数据库链接不存在!" );
        }
        sql = dataSetService.mergeSql ( sql, field, defaultValue );
        SqlRowSet rs = jdbcTemplate.queryForRowSet ( sql );
        int count = rs.getMetaData ( ).getColumnCount ( );
        for (int i = 1; i <= count; i++) {
            Map map = new HashMap ( );
            map.put ( "name", rs.getMetaData ( ).getColumnLabel ( i ) );
            map.put ( "type", rs.getMetaData ( ).getColumnTypeName ( i ) );
            map.put ( "label", rs.getMetaData ( ).getColumnLabel ( i ) );
            columnList.add ( map );
        }

        return ResponseEntity.ok ( columnList );
    }

    /**
     * 执行sql,预览数据
     *
     * @param sql
     * @return
     */
    @GetMapping(value = "/exec")
    public ResponseEntity exec(@RequestParam(value = "dataSourceId", required = false) String dataSourceId, @RequestParam(value = "sql", required = false) String sql, @RequestParam(value = "field[]", required = false) String[] field, @RequestParam(value = "defaultValue[]", required = false) String[] defaultValue) {
        try {
            JdbcTemplate jdbcTemplate = DBPool.getInstance ( ).getJdbcTemplateByDsId ( dataSourceId );
            if ( jdbcTemplate == null ) {
                return ResponseEntity.badRequest ( ).body ( "数据库链接不存在!" );
            }

            if ( sql.contains ( "delete" ) || sql.contains ( "update" ) ) {
                return ResponseEntity.badRequest ( ).body ( "只允许查询操作!" );
            }
            ;
            sql = dataSetService.mergeSql ( sql, field, defaultValue );

            List <Map <String, Object>> list = jdbcTemplate.queryForList ( sql );
            //数据格式转换
            JSONArray data = dataSetService.toJSON ( list );

            //返回结果
            return ResponseUtil.newInstance ( ).add ( "html", dataSetService.toHTML ( data ) ).add ( "json", list ).add ( "xml", dataSetService.toXML ( data ) ).ok ( );
        } catch (Exception e) {
            return ResponseEntity.badRequest ( ).body ( e.getCause ( ).getLocalizedMessage ( ) );
        }
    }

    /**
     * 执行sql,预览数据
     *
     * @param id
     * @return
     */
    @GetMapping(value = "/getData/{id}/{type}")
    public ResponseEntity getData(@PathVariable("id") String id, @PathVariable("type") String type, HttpServletRequest request) {
        Enumeration <String> names = request.getParameterNames ( );
        DataSet dataSet = dataSetService.getById ( id );
        try {
            JdbcTemplate jdbcTemplate = DBPool.getInstance ( ).getJdbcTemplateByEnName ( dataSet.getDataSourceId ( ) );
            if ( jdbcTemplate == null ) {
                return ResponseEntity.badRequest ( ).body ( "数据库链接不存在!" );
            }
            Map paramsMap = dataParamService.getParamsForMap ( id );
            while (names.hasMoreElements ( )) {
                String param = names.nextElement ( );
                paramsMap.put ( param, request.getParameter ( param ) );
            }

            String sql = dataSetService.mergeSql ( dataSet.getSqlCmd ( ), paramsMap );
            List <Map <String, Object>> list = jdbcTemplate.queryForList ( sql );
            //数据格式转换
            JSONArray data = dataSetService.toJSON ( list );

            if ( "html".equals ( type ) ) {
                return ResponseEntity.ok ( dataSetService.toHTML ( data ) );
            } else if ( "xml".equals ( type ) ) {
                return ResponseEntity.ok ( dataSetService.toXML ( data ) );
            } else {
                return ResponseEntity.ok ( list );
            }
        } catch (Exception e) {
            return ResponseEntity.badRequest ( ).body ( e.getCause ( ).getLocalizedMessage ( ) );
        }
    }


}
